/****************************************************************
 *
 * Header Files
 *
 ***************************************************************/

#include "ctc_cli.h"
#include "ctc_cli_common.h"
#include "ctc_security_cli.h"
#include "ctcs_api.h"
#include "ctc_security.h"

CTC_CLI(ctc_cli_asw_security_mac_security_set_learn_limit,
        ctc_cli_asw_security_mac_security_set_learn_limit_cmd,
        "security learn-limit type (port GPHYPORT_ID ) (maximum NUM) action (none|fwd|discard|redirect-to-cpu)",
        CTC_CLI_SECURITY_STR,
        "Learn limit",
        "Learn limit type",
        "Port based learn limit",
        CTC_CLI_GPORT_DESC,
        "Maximum number",
        "0x0 means disable",
        "The action of mac limit",
        "Do nothing",
        "Forwarding packet",
        "Discard packet",
        "Redirect to cpu")
{
    int32 ret = 0;
    ctc_security_learn_limit_t learn_limit;
    uint8 index = 0;

    sal_memset(&learn_limit, 0, sizeof(ctc_security_learn_limit_t));

    if (CLI_CLI_STR_EQUAL("port", index))
    {
        learn_limit.limit_type = CTC_SECURITY_LEARN_LIMIT_TYPE_PORT;
        index ++;
        CTC_CLI_GET_UINT16_RANGE("gport", learn_limit.gport, argv[index], 0, CTC_MAX_UINT16_VALUE);
    }

    index ++;
    if (CLI_CLI_STR_EQUAL("maximum", index))
    {
        index ++;
        CTC_CLI_GET_UINT32_RANGE("max num", learn_limit.limit_num, argv[index], 0, CTC_MAX_UINT32_VALUE);
    }

    index ++;
    if (CLI_CLI_STR_EQUAL("f", index))
    {
        learn_limit.limit_action = CTC_MACLIMIT_ACTION_FWD;
    }
    else if (CLI_CLI_STR_EQUAL("d", index))
    {

        learn_limit.limit_action  = CTC_MACLIMIT_ACTION_DISCARD;
    }
    else if (CLI_CLI_STR_EQUAL("r", index))
    {

        learn_limit.limit_action  = CTC_MACLIMIT_ACTION_TOCPU;
    }
    ret = ctcs_mac_security_set_learn_limit(g_api_lchip, &learn_limit);

    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s \n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return ret;
}

CTC_CLI(ctc_cli_asw_security_storm_ctl_set_config,
        ctc_cli_asw_security_storm_ctl_set_config_cmd,
        "security storm-ctl (port GPHYPORT_ID| vlan VLAN_ID) (enable|disable) mode (pps | kbps ) (threshold THRESHOLD_NUM) \
    type(broadcast|known-multicast|unknown-multicast|unknown-unicast)",
        CTC_CLI_SECURITY_STR,
        "Storm control",
        "Port based Storm control",
        CTC_CLI_GPHYPORT_ID_DESC,
        "Vlan based Storm control",
        CTC_CLI_VLAN_RANGE_DESC,
        CTC_CLI_ENABLE,
        CTC_CLI_DISABLE,
        "The mode of storm control",
        "Packet per second",
        "Bytes per second",
        "Threshold",
        "Bps <0-PortMaxSpeed/8>, must be in multiples of 1000, pps:(<0-PortMaxSpeed/(8*84)>) ",
        "The type of storm control",
        "Broadcast",
        "Known multicast",
        "Unknown multicast",
        "Unknown unicast"
        )
{
    uint16 gport_id = 0;
    uint16 vlan_id = 0;
    uint32 value = 0;
    int32 ret = 0;
    uint8 index = 0;
    ctc_security_storm_ctl_type_t type = 0;
    ctc_security_stmctl_cfg_t  stmctl_cfg;

    sal_memset(&stmctl_cfg, 0, sizeof(stmctl_cfg));

    index = CTC_CLI_GET_ARGC_INDEX("port");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT16_RANGE("gport", gport_id, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
        stmctl_cfg.gport = gport_id;
        stmctl_cfg.op = CTC_SECURITY_STORM_CTL_OP_PORT;
    }

    index = CTC_CLI_GET_ARGC_INDEX("vlan");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT16_RANGE("vlan id", vlan_id, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
        stmctl_cfg.vlan_id = vlan_id;
        stmctl_cfg.op = CTC_SECURITY_STORM_CTL_OP_VLAN;
    }

    index = CTC_CLI_GET_ARGC_INDEX("enable");
    if (0xFF != index)
    {
        stmctl_cfg.storm_en = 1;
    }
    else
    {
        stmctl_cfg.storm_en = 0;
    }

    index = CTC_CLI_GET_ARGC_INDEX("pps");
    if (0xFF != index)
    {
        stmctl_cfg.mode = CTC_SECURITY_STORM_CTL_MODE_PPS;
    }

    index = CTC_CLI_GET_ARGC_INDEX("kbps");
    if (0xFF != index)
    {
        stmctl_cfg.mode = CTC_SECURITY_STORM_CTL_MODE_KBPS;
    }

    index = CTC_CLI_GET_ARGC_INDEX("threshold");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT32_RANGE("threshold", value, argv[index + 1], 0, CTC_MAX_UINT32_VALUE);
        stmctl_cfg.threshold = value;
    }

    index = CTC_CLI_GET_ARGC_INDEX("broadcast");
    if (0xFF != index)
    {
        type = CTC_SECURITY_STORM_CTL_BCAST;
    }

    index = CTC_CLI_GET_ARGC_INDEX("known-multicast");
    if (0xFF != index)
    {
        type = CTC_SECURITY_STORM_CTL_KNOWN_MCAST;
    }

    index = CTC_CLI_GET_ARGC_INDEX("unknown-multicast");
    if (0xFF != index)
    {
        type = CTC_SECURITY_STORM_CTL_UNKNOWN_MCAST;
    }

    index = CTC_CLI_GET_ARGC_INDEX("unknown-unicast");
    if (0xFF != index)
    {
        type = CTC_SECURITY_STORM_CTL_UNKNOWN_UCAST;
    }
    stmctl_cfg.type = type;
    ret = ctcs_storm_ctl_set_cfg(g_api_lchip, &stmctl_cfg);

    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s \n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_security_storm_ctl_show_cfg,
        ctc_cli_asw_security_storm_ctl_show_cfg_cmd,
        "show security storm-ctl (port GPHYPORT_ID| vlan VLAN_ID) \
    (broadcast|known-multicast|unknown-multicast|known-unicast|unknown-unicast)",
        CTC_CLI_SHOW_STR,
        CTC_CLI_SECURITY_STR,
        "Storm control",
        "Port configure",
        CTC_CLI_GPORT_DESC,
        "Vlan based Storm control",
        CTC_CLI_VLAN_RANGE_DESC,
        "Broadcast",
        "Known multicast",
        "Unknown multicast",
        "Known unicast",
        "Unknown unicast"
        )
{
    uint16 gport_id = 0;
    uint16 vlan_id = 0;
    int32 ret = 0;
    ctc_security_storm_ctl_type_t type = 0;
    ctc_security_stmctl_cfg_t stmctl_cfg;
    uint16 index  = 0;

    sal_memset(&stmctl_cfg, 0, sizeof(ctc_security_stmctl_cfg_t));

    index = CTC_CLI_GET_ARGC_INDEX("port");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT16_RANGE("gport", gport_id, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
        stmctl_cfg.gport = gport_id;
        stmctl_cfg.op = CTC_SECURITY_STORM_CTL_OP_PORT;
        ctc_cli_out("gport 0x%04X storm control:\n", gport_id);
    }

    index = CTC_CLI_GET_ARGC_INDEX("vlan");
    if (0xFF != index)
    {
        CTC_CLI_GET_UINT16_RANGE("vlan id", vlan_id, argv[index + 1], 0, CTC_MAX_UINT16_VALUE);
        stmctl_cfg.vlan_id = vlan_id;
        stmctl_cfg.op = CTC_SECURITY_STORM_CTL_OP_VLAN;
        ctc_cli_out("Vlan %d storm control:\n", vlan_id);
    }

    index = CTC_CLI_GET_ARGC_INDEX("broadcast");
    if (0xFF != index)
    {
        type = CTC_SECURITY_STORM_CTL_BCAST;
    }

    index = CTC_CLI_GET_ARGC_INDEX("known-multicast");
    if (0xFF != index)
    {
        type = CTC_SECURITY_STORM_CTL_KNOWN_MCAST;
    }

    index = CTC_CLI_GET_ARGC_INDEX("unknown-multicast");
    if (0xFF != index)
    {
        type = CTC_SECURITY_STORM_CTL_UNKNOWN_MCAST;
    }

    index = CTC_CLI_GET_ARGC_INDEX("unknown-unicast");
    if (0xFF != index)
    {
        type = CTC_SECURITY_STORM_CTL_UNKNOWN_UCAST;
    }


    stmctl_cfg.type  = type;
    ret = ctcs_storm_ctl_get_cfg(g_api_lchip, &stmctl_cfg);
    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s \n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    ctc_cli_out("\ttype:");

    switch (stmctl_cfg.type)
    {
    case CTC_SECURITY_STORM_CTL_BCAST:
        ctc_cli_out("broadcast\n");
        break;

    case CTC_SECURITY_STORM_CTL_KNOWN_MCAST:
        ctc_cli_out("known-multicast\n");
        break;

    case CTC_SECURITY_STORM_CTL_UNKNOWN_MCAST:
        ctc_cli_out("unknown-multicast\n");
        break;

    case CTC_SECURITY_STORM_CTL_UNKNOWN_UCAST:
        ctc_cli_out("unknown-unicast\n");
        break;

    default:
        ctc_cli_out("none\n");
        return CLI_ERROR;
        break;
    }

    ctc_cli_out("\tenable:%d\n", stmctl_cfg.storm_en);
    if (CTC_SECURITY_STORM_CTL_MODE_PPS == stmctl_cfg.mode)
    {
        ctc_cli_out("\tthreshold:%u (packets per second)\n", stmctl_cfg.threshold);
    }
    else if (CTC_SECURITY_STORM_CTL_MODE_KBPS == stmctl_cfg.mode)
    {
        ctc_cli_out("\tthreshold:%u (k bits per second)\n", stmctl_cfg.threshold);
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_security_storm_ctl_set_global_cfg,
        ctc_cli_asw_security_storm_ctl_set_global_cfg_cmd,
        "security storm-ctl {ipg (enable|disable)}",
        CTC_CLI_SECURITY_STR,
        "Storm control",
        "Ipg",
        CTC_CLI_ENABLE,
        CTC_CLI_DISABLE
        )
{
    int32 ret = 0;
    uint8 index = 0;
    ctc_security_stmctl_glb_cfg_t stmctl_glb_cfg;

    sal_memset(&stmctl_glb_cfg, 0, sizeof(ctc_security_stmctl_glb_cfg_t));

    index = CTC_CLI_GET_ARGC_INDEX("ipg");
    if (0xFF != index)
    {
        if (CLI_CLI_STR_EQUAL("enable", index + 1))
        {
            stmctl_glb_cfg.ipg_en = 1;
        }
        else if (CLI_CLI_STR_EQUAL("disable", index + 1))
        {
            stmctl_glb_cfg.ipg_en = 0;
        }
    }
    ret = ctcs_storm_ctl_set_global_cfg(g_api_lchip, &stmctl_glb_cfg);
    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s \n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_security_storm_ctl_show_global_cfg,
        ctc_cli_asw_security_storm_ctl_show_global_cfg_cmd,
        "show security storm-ctl glb-cfg",
        CTC_CLI_SHOW_STR,
        CTC_CLI_SECURITY_STR,
        "Storm control",
        "Global configure")
{
    int32 ret = 0;
    ctc_security_stmctl_glb_cfg_t glb_cfg;

    sal_memset(&glb_cfg, 0, sizeof(ctc_security_stmctl_glb_cfg_t));


    ret = ctcs_storm_ctl_get_global_cfg(g_api_lchip, &glb_cfg);

    if (ret < 0)
    {
        ctc_cli_out("%% ret = %d, %s \n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    ctc_cli_out("Global storm control:\n");
    ctc_cli_out("\tipg_en:%d\n", glb_cfg.ipg_en);

    return CLI_SUCCESS;
}

CTC_CLI(ctc_cli_asw_security_mac_security_set_port_learn_limit,
        ctc_cli_asw_security_mac_security_set_port_learn_limit_cmd,
        "security mac-limit port GPHYPORT_ID action (none|fwd|discard|redirect-to-cpu)",
        CTC_CLI_SECURITY_STR,
        "Mac limit",
        "Port based mac limit",
        CTC_CLI_GPHYPORT_ID_DESC,
        "The action of mac limit",
        "Do nothing",
        "Forwarding packet",
        "Discard packet",
        "Redirect to cpu")
{
    int32 ret = 0;
    uint16 gport_id = 0;

    ctc_maclimit_action_t  action = CTC_MACLIMIT_ACTION_NONE;

    CTC_CLI_GET_UINT16_RANGE("gport", gport_id, argv[0], 0, CTC_MAX_UINT16_VALUE);

    if (CLI_CLI_STR_EQUAL("n", 1))
    {
        action = CTC_MACLIMIT_ACTION_NONE;
    }
    else if (CLI_CLI_STR_EQUAL("f", 1))
    {
        action = CTC_MACLIMIT_ACTION_FWD;
    }
    else if (CLI_CLI_STR_EQUAL("r", 1))
    {
        action = CTC_MACLIMIT_ACTION_TOCPU;
    }

    if (CLI_CLI_STR_EQUAL("d", 1))
    {
        action = CTC_MACLIMIT_ACTION_DISCARD;
    }

    ret = ctcs_mac_security_set_port_mac_limit(g_api_lchip, gport_id, action);

    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d, %s\n", ret, ctc_get_error_desc(ret));
    }

    return ret;
}

CTC_CLI(ctc_cli_asw_security_mac_security_show_mac_limit,
        ctc_cli_asw_security_mac_security_show_mac_limit_cmd,
        "show security mac-limit port VALUE",
        CTC_CLI_SHOW_STR,
        CTC_CLI_SECURITY_STR,
        "Mac limit",
        "Port based mac limit",
        "The value of gport Id")
{
    int32 ret = 0;
    uint16 value = 0;
    ctc_maclimit_action_t  action;

    ctc_cli_out("===============================\n");
    CTC_CLI_GET_UINT32_RANGE("value", value, argv[0], 0, CTC_MAX_UINT32_VALUE);


    ret = ctcs_mac_security_get_port_mac_limit(g_api_lchip, value, &action);
    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d, %s\n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    ctc_cli_out("Port:%d action:%u\n", value, action);

    ctc_cli_out("===============================\n");

    return CLI_SUCCESS;

}

CTC_CLI(ctc_cli_asw_security_mac_security_show_learn_limit,
        ctc_cli_asw_security_mac_security_show_learn_limit_cmd,
        "show security learn-limit type (port GPHYPORT_ID)",
        CTC_CLI_SHOW_STR,
        CTC_CLI_SECURITY_STR,
        "Learn limit",
        "Learn limit type",
        "Port based learn limit",
        CTC_CLI_GPORT_DESC)
{
    int32 ret = 0;
    ctc_security_learn_limit_t learn_limit;
    uint8 index = 0;
    uint32 limit_num = 0;
    uint8 action = 0;
    char action_str[CTC_MACLIMIT_ACTION_TOCPU + 1][32] = {{"None"}, {"forwarding packet"}, {"discard packet"}, {"redirect to cpu"}};

    sal_memset(&learn_limit, 0, sizeof(ctc_security_learn_limit_t));
    if (CLI_CLI_STR_EQUAL("port", index))
    {
        learn_limit.limit_type = CTC_SECURITY_LEARN_LIMIT_TYPE_PORT;
        index ++;
        CTC_CLI_GET_UINT32_RANGE("gport", learn_limit.gport, argv[index], 0, CTC_MAX_UINT32_VALUE);
    }
    
    ret = ctcs_mac_security_get_learn_limit(g_api_lchip, &learn_limit);
    if (ret < 0)
    {
        ctc_cli_out("%% ret =%d, %s\n", ret, ctc_get_error_desc(ret));
        return CLI_ERROR;
    }

    action = learn_limit.limit_action;
    limit_num = learn_limit.limit_num;

    ctc_cli_out("Port 0x%x :\n", learn_limit.gport);
    ctc_cli_out("Mac limit action %s\n", action_str[action]);
    if (0x0 != limit_num)
    {
        ctc_cli_out("Max number is  0x%x\n", limit_num);
    }
    else
    {
        ctc_cli_out("Max number is  %s\n", "disabled");
    }

    return ret;
}

int32
ctc_asw_security_cli_init(uint8 cli_tree_mode)
{
    install_element(cli_tree_mode, &ctc_cli_asw_security_mac_security_set_learn_limit_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_security_storm_ctl_set_config_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_security_storm_ctl_show_cfg_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_security_storm_ctl_set_global_cfg_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_security_storm_ctl_show_global_cfg_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_security_mac_security_set_port_learn_limit_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_security_mac_security_show_mac_limit_cmd);
    install_element(cli_tree_mode, &ctc_cli_asw_security_mac_security_show_learn_limit_cmd);
    return CLI_SUCCESS;

}


